class Person {
  // 构造函数，用于初始化对象的属性
  constructor(name, age) {
    this.name = name; // this 指向新创建的对象实例
    this.age = age;
  }

  // 类的方法
  sayHello() {
    console.log(`大家好，我叫 ${this.name}，今年 ${this.age} 岁。`);
  }

  // 另一个方法
  getAge() {
    return this.age;
  }
}

// 使用 new 关键字创建 Person 类的实例
const person1 = new Person('张三', 30);
const person2 = new Person('李四', 25);

// 调用实例的方法
person1.sayHello(); // 输出: 大家好，我叫 张三，今年 30 岁。
console.log(person2.getAge()); // 输出: 25

class Student extends Person {
  // 子类的构造函数
  constructor(name, age, studentId) {
    // 必须先调用 super() 来初始化父类的属性
    super(name, age); 
    
    // 然后再初始化子类特有的属性
    this.studentId = studentId;
  }

  // 子类可以拥有自己的新方法
  study() {
    console.log(`${this.name} 正在努力学习...`);
  }

  // 子类可以重写（Override）父类的方法
  sayHello() {
    // 调用父类的 sayHello 方法，并增加自己的逻辑
    super.sayHello();
    console.log(`我的学号是 ${this.studentId}。`);
  }
}

// 创建一个 Student 类的实例
const student1 = new Student('王五', 20, '2023001');

// 调用子类的方法
student1.sayHello();
/* 输出:
   大家好，我叫 王五，今年 20 岁。
   我的学号是 2023001。
*/

student1.study(); // 输出: 王五 正在努力学习...

// 继承了父类的方法
console.log(student1.getAge()); // 输出: 20
